<?php  
/** 
 * Pagination Component, responsible for managing the DATA required for pagination. 
 */ 
class PaginationComponent extends Object 
{ 
    // Configuration/Default variables 
/** 
 * Specify whether the component will use AJAX links if available. 
 * Tests for the presence of the RequestHandler component and if present will generate 
 * AJAX links. However, if the prototype library js has not been included, normal updates 
 * will take place. 
 * 
 * @var boolean 
 * @access public 
 */ 
    var $ajaxAutoDetect = true; 
/** 
 * Specify the div to update if using ajax updates 
 * 
 * @var string 
 * @access public 
 */ 
    var $ajaxDivUpdate = "content"; 
/** 
 * The id of a form ID to be submitted with all pagination ajax links. 
 * 
 * @var string 
 * @access public 
 */ 
    var $ajaxFormId = NULL; 
/** 
 * Specify link style 
 * 
 * @var string "html"/"ajax" 
 * @access public 
 */ 
    var $style = "html"; 
/** 
 * Specify link parameter style 
 * 
 * @var string "get"/"pretty" 
 * @access public 
 */ 
    var $paramStyle = "get"; 
/** 
 * Used only for pretty style urls - must match the  
 * 
 * @var string "get"/"pretty" 
 * @access public 
 */ 
    var $paramSeperator = "/"; 
/** 
 * Specify DEFAULT start page number 
 * 
 * @var integer 
 * @access public 
 */ 
    var $page = 1; 
/** 
 * Specify DEFAULT number of items to be displayed per page. Also used as the limit 
 * for the subsequent SQL search. 
 * 
 * @var integer 
 * @access public 
 */ 
    var $show = 3; 
/** 
 * Specify DEFAULT sort column. 
 * 
 * @var string 
 * @access public 
 */ 
    var $sortBy = 'id'; 
/** 
 * Specify DEFAULT sort direction. 
 * 
 * @var string 
 * @access public 
 */ 
    var $direction = 'ASC'; 
/** 
 * Specify the maximum number of pages to be included in the list of pages. Should be an odd number, otherwise rounded down. 
 * 
 * @var integer 
 * @access public 
 */ 
    var $maxPages = 10; 
/** 
 * Options for results per page. 
 * 
 * @var array 
 * @access public 
 */ 
    var $resultsPerPage = array(2,5,10,20,50,100,500); 
/** 
 * Show links to the first and last page, if the number of pages exceeds the maxPage count. 
 * 
 * @var boolean 
 * @access public 
 */ 
    var $showLimits = true; 
/** 
 * An array of parameter names which cannot be specified by the url 
 * 
 * @var array 
 * @access public 
 */ 
    var $privateParams = Array(); 

    // Do not edit below this line unless you wish to customize the core functionality of this Component 
/** 
 * Place holder for the sort class. Irrelavent for models without associations 
 * 
 * @var boolean 
 * @access private 
 */ 
    var $sortByClass = NULL; 
/** 
 * Place holder for the model class. 
 * 
 * @var boolean 
 * @access private 
 */ 
    var $modelClass = NULL; 
/** 
 * Place holder for the base url 
 * 
 * @var boolean 
 * @access private 
 */ 
    var $url = NULL; 
/** 
 * Place holder for the controller 
 * 
 * @var boolean 
 * @access private 
 */ 
    var $controller = true; 
/** 
 * Place holder for the sanitize object 
 * 
 * @var boolean 
 * @access private 
 */ 
    var $sanitize = true; 
/** 
 * Place holder for the data array passed to the view 
 * 
 * @var boolean 
 * @access private 
 */ 
    var $paging; 

/** 
 * Startup - Link the component to the controller. 
 * 
 * @param controller 
 */ 
    function startup(&$controller) 
    { 
        $this->controller =& $controller;         
    } 
/** 
 * Initialize the pagination data. 
 * 
 * @param unknown 
 * @param array 
 * @options array 
 * @return array 
 */ 
    function init($criteria=NULL,$parameters=Array(),$options=Array(),$total,$rownum,$sortClass) 
    { 
        uses('sanitize'); 
        $show=$rownum;
        //echo $show;
        $this->total=$total;
        $this->sortByClass=$sortClass;
        $this->Sanitize = &new Sanitize; 
        //pr($parameters);
        $this->_initFields($options); 
        $this->_checkAjax(); 
        $this->_initSort(); 
        
        //pr($this->_initSort());
        $this->_initPaging($parameters,$rownum); 
        $this->_initURL(); 

        $this->_setParameter("show",$parameters); 
        // If the number of results per page isn't in the list, reset to default 
        if ((isset($this->paging["show"]))&&(!in_array($this->paging["show"],$this->resultsPerPage))) 
        { 
            $this->paging["show"]=$this->paging['Defaults']['show']; 
        } 
         
        $this->_setParameter("page",$parameters); 
        $this->_setParameter("sortBy",$parameters); 
        $this->_setParameter("sortByClass",$parameters); // Overriding the model class if specified. 
        $this->_setParameter("direction",$parameters); 

        $this->_check4Form(); 

        $this->_setPrivateParameter("ajaxDivUpdate"); 
        $this->_setPrivateParameter("ajaxFormId"); 
        $this->_setPrivateParameter("maxPages"); 
        $this->_setPrivateParameter("showLimits"); 
        $this->_setPrivateParameter("style"); 
        $this->_setPrivateParameter("paramStyle"); 
        $this->_setPrivateParameter("paramSeperator"); 
        $this->_setPrivateParameter("url"); 

        if (isset($this->total)) // If the field is already set, we  passed in the options the total number of results 
        { 
            $count = $this->total; 
        } 
        else 
        { 
            $count = $this->controller->{$this->modelClass}->findCount($criteria,0);     
        } 
        
        $this->checkPage($count); 
        $this->paging['total'] = $count; 
        $this->trimResultsPerPage($count); 
        //echo $count;
        $this->_setPrivateParameter("resultsPerPage"); 
        //$this->paging['show']=$rownum;
        $this->paging['pageCount'] = ceil($count / $this->paging['show'] ); 
        //echo $this->paging['show'];
        $this->controller->set('paging',$this->paging); 
        $this->order = $this->paging['sortByClass'].".".$this->paging['sortBy'].' '.strtoupper($this->paging['direction']); 
        // For backwards compatability & clarity 
        $this->limit = $this->paging['show']; 
        $this->page = $this->paging['page']; 
        //echo  $this->paging['page'];
        // For less code in the calling method.. 
        return ($this->paging['page']); 
    } 
     
/** 
 * Don't give the choice to display pages with no results 
 * 
 * @param integer 
 */ 
    function trimResultsPerPage ($count = 0) 
    { 
        while (($limit = current($this->resultsPerPage))&&(!isset($capKey)))  
        { 
            if ($limit >= $count)  
            { 
                $capKey = key($this->resultsPerPage); 
            } 
            next($this->resultsPerPage); 
         
            if (isset($capKey)) 
            { 
                array_splice($this->resultsPerPage, ($capKey+1)); 
            } 
        } 
    } 

/** 
 * Set the page to the last if there would be no results, and to 1 if a negetive 
 * page number is specified 
 * 
 * @param integer 
 */ 
    function checkPage ($count = 0)  
    { 
      if ((($this->paging['page']-1)*$this->paging['show'])>=$count)  
      { 
            $this->paging['page'] = floor($count/$this->paging['show']+0.99); 
      } 
    } 
     
/** 
 * Set Object fields 
 * 
 * @param unknown 
 */ 
    function _initFields($options) 
    { 
        foreach($options as $option=>$val) 
        { 
            $this->$option = $val; 
        } 
    } 
/** 
 * Set Pagination with default Parameters 
 * 
 * @param unknown 
 */ 
    function _initPaging($parameters,$rownum) 
    {   
        
    //	pr($parameters);
        $this->paging['importParams']=$parameters; 
        $this->paging['Defaults'] = Array ( 
                                        "page"=>$this->page, 
                                        "show"=>$rownum, 
                                        "sortBy"=>$this->sortBy, 
                                        "sortByClass"=>$this->sortByClass, 
                                        "direction"=>$this->direction 
                                            );    
    // pr($this->paging);
    } 
/** 
 * If everything is in place, use Ajax by default 
 * 
 * @param unknown 
 */ 
    function _checkAjax() 
    { 
        if (($this->ajaxAutoDetect==true)&&(isset($this->controller->RequestHandler)&&(in_array("Ajax",$this->controller->helpers)))) 
        { 
            $this->style = "ajax";             
        } 
    } 

/** 
 * Set the DEFAULT sort class 
 * 
 * @param unknown 
 */ 
    function _initSort() 
    { 
        if (!$this->modelClass) 
        { 
            $ModelClass = $this->modelClass = $this->controller->modelClass; 
        } 
        else 
        { 
            $ModelClass = $this->modelClass; 
        } 
        if (!$this->sortBy) 
        { 
        $this->sortBy = $this->controller->$ModelClass->primaryKey; 
        } 
        if (!$this->sortByClass) 
        { 
            $this->sortByClass = $ModelClass; 
        } 
    } 

/** 
 * Set the base url for updates. 
 * 
 * @param unknown 
 */ 
    function _initURL() 
    { 
        if ($this->url) // A url was specified in the paramters 
        { 
            if (substr($this->url, -1, 1)<>"/") 
            { 
                $this->url .= "/"; 
            } 
        } 
        else // No url in the parameters, derive it. 
        { 
            if ($this->paramStyle=="get") 
            { 
                $this->url = str_replace($this->controller->webroot,"/",$this->controller->here); 
            } 
            else 
            { 
                $this->url = ""; 
                if (isset($this->controller->params['admin'])) 
                { 
                    $this->url .= "/".$this->controller->params['admin']; 
                    $action = substr($this->controller->action, strlen($this->controller->params['admin']."_")); 
                } 
                else 
                { 
                    $action = $this->controller->action; 
                } 
                if ($this->controller->plugin) 
                { 
                    $this->url .= "/".$this->controller->plugin; 
                } 
                $this->url .= "/".$this->controller->name; 
                $this->url .= "/".$action; 
                if (isset($this->paging['importParams']['_unamedParameters'])) 
                { 
                    $unnamedString = implode ("/", $this->paging['importParams']['_unamedParameters']); 
                    $this->url .= "/".$unnamedString; 
                    unset($this->paging['importParams']['_unamedParameters']); 
                } 
                $this->url .= "/"; 
            } 
        } 
        if (defined('BASE_URL')) { // Hack for no mod_rewrite 
            $this->url = preg_replace( "!".BASE_URL."!", '', $this->url); // Remove the base from the url 
            $this->url = preg_replace("!\?.*!", '', $this->url); // Remove the get parameters 
        } 
    } 

/** 
 * If the parameters have been changed/set by a form action, update the params array. 
 * Would perhaps be best to redirect to the equivalent url, which isn't implemented as 
 * the relavent method is in the helper and as such inaccessible here. 
 * 
 * @param unknown 
 */ 
    function _check4Form() 
    { 
        if(isset($this->controller->data['pagination'])) 
        { 
            if (isset($this->controller->data['pagination']['sortByComposite'])) 
            { 
                $Composite = Array(); 
                $Composite = explode("::",$this->controller->data['pagination']['sortByComposite']); 
                if (isset($Composite[0])) 
                { 
                    $this->controller->data['pagination']['sortBy'] = $Composite[0];     
                } 
                if (isset($Composite[1])) 
                { 
                    $this->controller->data['pagination']['direction'] = $Composite[1];     
                } 
                if (isset($Composite[2])) 
                { 
                    $this->controller->data['pagination']['sortByClass'] = $Composite[2];     
                } 
                else 
                { 
                    $this->controller->data['pagination']['sortByClass'] = $this->paging['Defaults']['sortByClass']; 
                } 
                unset($this->controller->data['pagination']['sortByComposite']);             
            } 
            foreach($this->controller->data['pagination'] as $parameter=>$value) 
            { 
                 
                if (!in_array($parameter, $this->privateParams)) 
                { 
                    $this->paging[$parameter] = $this->Sanitize->paranoid($value,array("-","_")); 
                }                 
            } 
        } 
    } 

/** 
 * Set a parameter to be passed to the view which cannot be specified/overriden from the url. 
 * 
 * @param unknown 
 */ 
    function _setPrivateParameter($parameter) 
    { 
        $this->paging[$parameter]= $this->$parameter; 
    } 

/** 
 * Set a parameter to be passed to the view overriden from the url if present. 
 * 
 * @param unknown 
 * @param array 
 * @param field 
 */ 
    function _setParameter($parameter,$parameters=Array(),$field=NULL) 
    { 
        $field = $field?$field:$parameter; 

        if (in_array($parameter, $this->privateParams)) 
        { 
            $this->paging[$field] = $this->paging['Defaults'][$field]; 
        } 
        else 
        { 
            if ($this->paramStyle=="get") 
            { 
                if (isset($_GET[$parameter])) 
                { 
                    $this->paging[$field] = $this->Sanitize->paranoid($_GET[$parameter],array("-","_"));         
                } 
                else 
                { 
                    $this->paging[$field]= $this->$field; 
                } 
            } 
            elseif ($this->paramStyle=="pretty") 
            { 
                if (isset($parameters[$parameter])) 
                { 
                    $this->paging[$field] = $this->Sanitize->paranoid($parameters[$parameter],array("-","_"));         
                } 
                else 
                { 
                    $this->paging[$field]= $this->$field; 
                } 
            } 
            else 
            { 
                echo ("parameter error"); 
                die; 
            } 
        } 
    } 
} 
?>